package com.answer.constant;

import cn.hutool.core.io.FileUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * 代码生成器
 */
@Deprecated
public class CodeGenerator {

    /**
     * 程序入口：用于批量生成不同类型的Java代码文件
     * 根据提供的模板和数据参数，生成包括Controller、Service接口和实现类、DTO和VO等代码文件
     * 用法：修改生成参数和生成路径，注释掉不需要的生成逻辑，然后运行即可
     *
     * @param args 命令行参数，本程序不使用
     * @throws TemplateException 如果模板处理失败
     * @throws IOException 如果文件读写失败
     */
    public static void main(String[] args) throws TemplateException, IOException {
        // 定义生成代码所需的包名、数据名、数据键和首字母大写的键名
        String packageName = "com.answer";
        String dataName = "用户答案";
        String dataKey = "userAnswer";
        String upperDataKey = "UserAnswer";

        // 封装生成参数
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("packageName", packageName);
        dataModel.put("dataName", dataName);
        dataModel.put("dataKey", dataKey);
        dataModel.put("upperDataKey", upperDataKey);

        // 获取项目路径，用于指定模板和生成文件的位置
        String projectPath = System.getProperty("user.dir");
        // 模板文件路径和生成文件路径的默认值
        String inputPath = projectPath + File.separator + "src/main/resources/templates/模板名称.java.ftl";
        String outputPath = String.format("%s/generator/包名/%s类后缀.java", projectPath, upperDataKey);

        // 生成 Controller
        inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateController.java.ftl";
        outputPath = String.format("%s/generator/controller/%sController.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        System.out.println("生成 Controller 成功，文件路径：" + outputPath);

        // 生成 Service 接口和实现类
        // 生成 Service 接口
        inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateService.java.ftl";
        outputPath = String.format("%s/generator/service/%sService.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        System.out.println("生成 Service 接口成功，文件路径：" + outputPath);
        // 生成 Service 实现类
        inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateServiceImpl.java.ftl";
        outputPath = String.format("%s/generator/service/impl/%sServiceImpl.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        System.out.println("生成 Service 实现类成功，文件路径：" + outputPath);

        // 生成数据模型封装类（包括 DTO 和 VO）
        // 生成 DTO
        inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateAddRequest.java.ftl";
        outputPath = String.format("%s/generator/model/dto/%sAddRequest.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateQueryRequest.java.ftl";
        outputPath = String.format("%s/generator/model/dto/%sQueryRequest.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateEditRequest.java.ftl";
        outputPath = String.format("%s/generator/model/dto/%sEditRequest.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateUpdateRequest.java.ftl";
        outputPath = String.format("%s/generator/model/dto/%sUpdateRequest.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        System.out.println("生成 DTO 成功，文件路径：" + outputPath);
        // 生成 VO
        inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateVO.java.ftl";
        outputPath = String.format("%s/generator/model/vo/%sVO.java", projectPath, upperDataKey);
        doGenerate(inputPath, outputPath, dataModel);
        System.out.println("生成 VO 成功，文件路径：" + outputPath);
    }

    /**
     * 生成文件
     * 使用FreeMarker模板根据提供的数据模型生成文件内容，并输出到指定路径
     *
     * @param inputPath  模板文件输入路径
     * @param outputPath 输出路径
     * @param model      数据模型
     * @throws IOException 如果无法读取模板文件或无法创建输出文件
     * @throws TemplateException 如果模板处理过程中出现错误
     */
    public static void doGenerate(String inputPath, String outputPath, Object model) throws IOException, TemplateException {
        // 初始化FreeMarker配置对象，并指定使用版本
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);

        // 设置模板文件目录，以便FreeMarker能够找到模板文件
        File templateDir = new File(inputPath).getParentFile();
        configuration.setDirectoryForTemplateLoading(templateDir);

        // 设置模板文件使用的字符集，确保中文等非ASCII字符不出现乱码
        configuration.setDefaultEncoding("utf-8");

        // 根据文件名获取模板对象，文件名由输入路径的文件名部分获得
        String templateName = new File(inputPath).getName();
        Template template = configuration.getTemplate(templateName);

        // 如果输出文件不存在，则创建之；如果其父目录不存在，也一并创建
        if (!FileUtil.exist(outputPath)) {
            FileUtil.touch(outputPath);
        }

        // 创建文件写入流，将模板处理后的结果写入到输出文件中
        Writer out = new FileWriter(outputPath);
        template.process(model, out);

        // 关闭写入流，释放资源
        out.close();
    }

}
